#include "MemoryMenager.h"
#include <stdlib.h>
#include <conio.h>
#include <string.h>
#include "List.h"


MemoryMenager::MemoryMenager(char * FN) : filename(NULL),myfile(FN,ios::in), CurrentIndex(0)
{
	filename = strdup(FN);
	pFreeList.addListItem(ListItem(0,1000));
	for(int i=0;i<1000;i++)
		Memory[i] = 0;
	for(int i=0;i<100;i++)
		Pointer[i] = NULL;

	Memory[0] = 1000;
}

MemoryMenager::~MemoryMenager()
{
delete []filename;
myfile.close();
}

MemoryMenager::MemoryAction MemoryMenager::getNextCommand()
{
MemoryAction AC;
char tmp[100];
if ( myfile.eof() )
	{
		AC.Index=  -1;
		return AC;
	}
else
	{
		myfile.getline(tmp,100);
		strcpy(CurrentAction,tmp);
		AC.Index =  (tmp[1] - '0') *10 + (tmp[2] - '0');
		AC.action = (tmp[4]=='-')?(fa_free):(fa_alloc);
		if (AC.action==fa_alloc)
			AC.Size  = (tmp[4] - '0') *100 + (tmp[5] - '0') *10 + (tmp[6] - '0');
		else
			AC.Size = -1;
	}

return AC;

}

void MemoryMenager::Memory_Allocation(MemoryAction MA)
{
int i=-1;
bool found = false;
while (++i<pFreeList.getListCount() && !found)
{
	//search for first fit block
	if (pFreeList[i]->getBlockSize()>= MA.Size)
	{
		found = true;
		break;
	}
}

// only in case current pfree bigger that MA
if (found)
{
	pFreeList[i]->setBlockSize(pFreeList[i]->getBlockSize() - MA.Size - 1);
	Memory[pFreeList[i]->getMemoryIndex()] = MA.Size;
	if (pFreeList[i]->getBlockSize()>=1) // there is more free space in this block
		Memory[pFreeList[i]->getMemoryIndex()+1 + MA.Size + 1] = Memory[pFreeList[i]->getMemoryIndex()+1]; //save pointer for next
	if (pFreeList[i]->getBlockSize()==0) // one unused block
		Memory[pFreeList[i]->getMemoryIndex() + MA.Size + 1] = UNUSEDBLOCK; //mark unused block

	
	Memory[pFreeList[i]->getMemoryIndex()+1] = 0; //reset pointer
	
	Pointer[MA.Index] = new ListItem(pFreeList[i]->getMemoryIndex(),MA.Size);
	pFreeList[i]->setMemoryIndex(pFreeList[i]->getMemoryIndex() + MA.Size + 1);	
	// when block size is (0,-1) = there are no more space, so need to remove this
	// free block from the list,otherwise,update what last from this block
	// in the memory.
	if (pFreeList[i]->getBlockSize()>=1)
		Memory[pFreeList[i]->getMemoryIndex()] = pFreeList[i]->getBlockSize();
	else
		pFreeList.deleteListItem(pFreeList[i]);
}


}

void MemoryMenager::Memory_Free(MemoryAction MA)
{
int i=0;
ListItem *p,*pnext;
while (i < pFreeList.getListCount() && pFreeList[i]->getMemoryIndex() < Pointer[MA.Index]->getMemoryIndex())
	i++;

pFreeList.addListItemBefore(ListItem(*Pointer[MA.Index]),pFreeList[i]);
Memory[pFreeList[i]->getMemoryIndex() + 1] = pFreeList[i+1]->getMemoryIndex();
//in case that we free block with 1 unused block, add this 1 block to the free space. 
if (Memory[pFreeList[i]->getMemoryIndex() + pFreeList[i]->getBlockSize() +1] == UNUSEDBLOCK)
{
	pFreeList[i]->setBlockSize(pFreeList[i]->getBlockSize()+1);
	Memory[pFreeList[i]->getMemoryIndex()]++;
}
delete Pointer[MA.Index]; Pointer[MA.Index] = NULL;

//code for removing ordered free blocks
p = pFreeList.getFirstItem();
while ((pnext=p->getNext()) !=NULL)
	{
		if (p->getMemoryIndex() + p->getBlockSize() + 1 == pnext->getMemoryIndex())
		{
				p->setBlockSize(p->getBlockSize() + pnext->getBlockSize() + 1); //set new block size
				for(int i=p->getMemoryIndex();i<p->getMemoryIndex() + p->getBlockSize();i++)
					Memory[i+1] = 0;
				Memory[p->getMemoryIndex()] = p->getBlockSize(); //set new size
				if (pnext->getNext() !=NULL) //if not the last block,update pointer
					Memory[p->getMemoryIndex() + 1] = pnext->getNext()->getMemoryIndex();
				pFreeList.deleteListItem(pnext); // delete the next (already updated by the p)
		}
		else
				p = pnext;	
		if (p==NULL)
			break;
	}

}

void MemoryMenager::Run()
{
	MemoryAction MA;
	char ch;
	while ((MA = getNextCommand()).Index !=-1)
	{
		if (MA.action == fa_alloc)
			Memory_Allocation(MA);
		
		if (MA.action == fa_free)
			Memory_Free(MA);

		CurrentIndex++;
		Draw();
		ch = getch();
		if (ch==27)
			break;
	}

}